﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetworkAssetManager.Entity;
using System.Management;
using log4net; 
namespace NetworkAssetManager.WMI
{
    class Printer
    {
        private static readonly ILog _logger = LogManager.GetLogger(typeof(Printer));

        private enum AvailabilityValues
        {
            NA,
            Other,
            Unknown,
            RunningOrFullPower,
            Warning,
            InTest,
            NotApplicable,
            PowerOff,
            OffLine,
            OffDuty,
            Degraded,
            NotInstalled,
            InstallError,
            PowerSaveUnknown,
            PowerSaveLowPowerMode,
            PowerSaveStandby,
            PowerCycle,
            PowerSaveWarning
        }

        private enum PrinterState
        {
            Paused = 1,
            Error,
            PendingDeletion,
            PaperJam,
            PaperOut,
            ManualFeed,
            PaperProblem,
            Offline,
            IOActive,
            Busy,
            Printing,
            OutputBinFull,
            NotAvailable,
            Waiting,
            Processing,
            Initialization,
            WarmingUp,
            TonerLow,
            NoToner,
            PagePunt,
            UserInterventionRequired,
            OutOfMemory,
            DoorOpen,
            ServerUnknown,
            PowerSave
        }

        private enum PrinterStatus
        {
            Other = 1,
            Unknown,
            Idle,
            Printing,
            WarmingUp,
            StoppedPrinting,
            Offline
        }

        private static string GetPrinterAttributes(uint value)
        {
            string attrib = string.Empty; 
            if ( (value & 0x01) == 0x01)
            {
                attrib += "Queued,"; 
            }
            if ((value & 0x02) == 0x02)
            {
                attrib += "Direct,";
            }
            if ((value & 0x04) == 0x04)
            {
                attrib += "Default,";
            }
            if ((value & 0x08) == 0x08)
            {
                attrib += "Shared,";
            }
            if ((value & 0x10) == 0x10)
            {
                attrib += "Network,";
            }
            if ((value & 0x20) == 0x20)
            {
                attrib += "Hidden,";
            }
            if ((value & 0x40) == 0x40)
            {
                attrib += "Local,";
            }
            if ((value & 0x80) == 0x80)
            {
                attrib += "EnableDevQ,";
            }
            if ((value & 0x100) == 0x100)
            {
                attrib += "Keep Printed Jobs,";
            }
            if ((value & 0x200) == 0x200)
            {
                attrib += "DoCompleteFirst,";
            }
            if ((value & 0x400) == 0x400)
            {
                attrib += "WorkOffline,";
            }
            if ((value & 0x800) == 0x800)
            {
                attrib += "EnableBIDI,";
            }
            if ((value & 0x1000) == 0x1000)
            {
                attrib += "Allow only raw data type jobs to be spooled.,";
            }
            if ((value & 0x2000) == 0x2000)
            {
                attrib += "Published,";
            }

            attrib= attrib.TrimEnd(',', ' ');
            return attrib; 
        }
        private static EntPrinter FillDetails(ManagementBaseObject obj)
        {
            EntPrinter objEntPrinter = new EntPrinter();
            try
            {
                objEntPrinter.Attributes = GetPrinterAttributes((uint)obj["Attributes"]); 
            }
            catch (Exception)
            {
                objEntPrinter.Attributes = ""; 
            }

            try
            {
                AvailabilityValues availability = (AvailabilityValues)WMIUtil.ToInteger(obj["Availability"]);
                objEntPrinter.Availability = WMIUtil.SplitCamelCase(availability.ToString());
            }   
            catch (Exception)
            {
                objEntPrinter.Availability = "";
            }

            try
            {
                objEntPrinter.AveragePagesPerMinute = WMIUtil.ToString(obj["AveragePagesPerMinute"]) + " pages per minute"; 
            }
            catch (Exception)
            {
                objEntPrinter.Availability = "";
            }

            try
            {
                objEntPrinter.Caption = WMIUtil.ToString(obj["Caption"]);
            }
            catch (Exception)
            {
                objEntPrinter.Caption = "";
            }

            try
            {
                objEntPrinter.HorizontalResolution = WMIUtil.ToInteger(obj["HorizontalResolution"]);
            }
            catch (Exception)
            {
                objEntPrinter.HorizontalResolution = 0;
            }

            try
            {
                objEntPrinter.VerticalResolution = WMIUtil.ToInteger(obj["VerticalResolution"]);
            }
            catch (Exception)
            {
                objEntPrinter.VerticalResolution = 0;
            }

            try
            {
                objEntPrinter.Local = (bool)obj["Local"]; 
            }
            catch (Exception)
            {
                objEntPrinter.Local = false;
            }

            try
            {
                objEntPrinter.Network = (bool)obj["Network"];
            }
            catch (Exception)
            {
                objEntPrinter.Network= false;
            }
            try
            {
                objEntPrinter.Shared = (bool)obj["Shared"];
            }
            catch (Exception)
            {
                objEntPrinter.Shared = false;
            }

            try
            {
                objEntPrinter.Location = WMIUtil.ToString(obj["Location"]);
            }   
            catch (Exception)
            {
                objEntPrinter.Location = "";
            }

            try
            {
                objEntPrinter.PortName = WMIUtil.ToString(obj["PortName"]);
            }
            catch (Exception)
            {
                objEntPrinter.PortName = "";
            }

            try
            {
                PrinterState priState = (PrinterState)WMIUtil.ToInteger(obj["PrinterState"]);
                objEntPrinter.PrinterState = WMIUtil.SplitCamelCase(priState.ToString());
            }
            catch (Exception)
            {
                objEntPrinter.PrinterState = "";
            }

            try
            {
                PrinterStatus priStatus = (PrinterStatus)WMIUtil.ToInteger(obj["PrinterStatus"]);
                objEntPrinter.PrinterStatus = WMIUtil.SplitCamelCase(priStatus.ToString());
            }
            catch (Exception)
            {
                objEntPrinter.PrinterStatus = "";
            }

            try
            {
                objEntPrinter.ServerName = WMIUtil.ToString(obj["ServerName"]);
            }
            catch (Exception)
            {
                objEntPrinter.ServerName = "";
            }

            try
            {
                objEntPrinter.ShareName = WMIUtil.ToString(obj["ShareName"]);
            }
            catch (Exception)
            {
                objEntPrinter.ShareName= "";
            }




            return objEntPrinter;
        }
        public static List<EntPrinter>GetPrinterDetails(ManagementScope scope)
        {
            _logger.Info("Collecting OS details for machine " + scope.Path.Server);

            ObjectQuery query = null;
            ManagementObjectSearcher searcher = null;
            ManagementObjectCollection objects = null;
            List<EntPrinter> lstPrinter = new List<EntPrinter>();

            try
            {
                query = new ObjectQuery("Select * from Win32_Printer");
                searcher = new ManagementObjectSearcher(scope, query);
                objects = searcher.Get();
                lstPrinter.Capacity = objects.Count;
                foreach (ManagementBaseObject obj in objects)
                {
                    lstPrinter.Add(FillDetails(obj));
                    obj.Dispose();
                }
            }
            catch (System.Exception e)
            {
                _logger.Error("Exception in printer collection " + e.Message);
            }
            finally
            {
                searcher.Dispose();
            }
            return lstPrinter;
        }

    }
}
